package tbs.framework.base.impls

import org.springframework.beans.factory.DisposableBean
import tbs.framework.interfaces.IBufferedConsumer
import tbs.framework.lock.ILock
import tbs.framework.utils.wrapper.LockWrapper
import java.util.*

/**
 * 这是一个简单的缓冲消费者实现，它继承了IBufferedConsumer接口，用于处理数据缓冲区。
 *
 * @param <T> 数据类型
 */
abstract class SimpleBufferedConsumer<T> : IBufferedConsumer<T>, DisposableBean {

    /**
     * 用于存储缓冲数据的队列
     */
    private val _queue: Queue<T>

    /**
     * 缓冲区限制的大小
     */
    private var _bufferSize = 0

    private val _lock: ILock;

    /**
     * 构造函数，初始化队列和缓冲区大小
     *
     * @param queue  队列
     * @param bufferSize 缓冲区大小
     */
    public constructor(queue: Queue<T>, lock: ILock, bufferSize: Int = 128) {
        _queue = queue
        _bufferSize = bufferSize
        this._lock = lock;
    }

    /**
     * 处理刷新时的错误
     *
     * @param e 异常
     * @param t 数据项
     * @return 如果处理成功，则返回true，否则返回false,若返回false会重新丢回队列中处理
     */
    abstract fun handleFlushError(e: Exception, t: T): Boolean

    /**
     * 刷新缓冲区，将缓冲区中的数据全部输出
     */
    override fun flush() {
        LockWrapper.instance.quickLock({
            val iter = _queue.iterator()
            while (iter.hasNext()) {
                val t = iter.next()
                try {
                    accept(t)
                    iter.remove()
                } catch (e: Exception) {
                    if (handleFlushError(e, t)) {
                        iter.remove()
                    }
                }
            }
        }, _lock)
    }

    /**
     * 获取缓冲区限制的大小
     *
     * @return 缓冲区限制的大小
     */
    override fun getBufferLimitedSize(): Int {
        return _bufferSize
    }

    /**
     * 获取缓冲区中已缓冲的数据数量
     *
     * @return 缓冲区中已缓冲的数据数量
     */
    override fun getBufferedSize(): Int {
        return _queue.size
    }

    /**
     * 检查缓冲区是否已满
     *
     * @return 如果缓冲区已满，则返回true，否则返回false
     */
    override fun isBufferFull(): Boolean {
        return bufferLimitedSize <= bufferedSize
    }

    /**
     * 将一个数据项添加到缓冲区
     *
     * @param t 数据项
     * @return 缓冲消费者对象
     */
    override fun buffer(t: T): IBufferedConsumer<T> {
        LockWrapper.instance.quickLock({
            _queue.add(t)
        }, _lock)

        if (isBufferFull()) {
            flush()
        }
        return this
    }

    /**
     * 销毁缓冲区
     */
    override fun destroy() {
        flush()
    }
}
